package com.chiao.core;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlTypeValue;
import org.springframework.jdbc.core.StatementCreatorUtils;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

/**
 * 
 * 数据库底层JDBC接口
 * 负责数据库的增、删、改、查等操作
 * @author zhangyinyou
 *
 */
@Repository
public class BaseDao extends AbsBaseDao {

	
	/**
	 * 更新单条sql语句
	 * @param sql	要执行的SQL语句
	 * @return	受影响行数
	 * @throws DataAccessException
	 */
	protected int update(String sql) {
		return getJdbcTemplate().update(sql);
	}
	
	/**
	 * 更新单条sql语句
	 * @param sql	要执行的SQL语句
	 * @param args	SQL语句中要替换的参数值
	 * @return	受影响行数
	 * @throws DataAccessException
	 */
	protected int update(String sql, Object... args) {
		return getJdbcTemplate().update(sql, args);
	}
	
	
	/**
	 * 插入数据时返回主键
	 * @param sql
	 * @param keyName 主键名称
	 * @param args
	 * @return
	 */
	protected Long saveForGeneratedKey(final String sql,final String keyName,final Object... args){
		KeyHolder keyHolder = new GeneratedKeyHolder();
		getJdbcTemplate().update(
		    new PreparedStatementCreator() {
		        public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
		            PreparedStatement ps = con.prepareStatement(sql, new String[] {keyName});
		            if(args!=null){
		            	for(int i=0;i<args.length;i++){
		            		StatementCreatorUtils.setParameterValue(ps, i+1, SqlTypeValue.TYPE_UNKNOWN, null,args[i]);
		            	}
		            }
		            return ps;
		        }
		    },
		    keyHolder);
		return keyHolder.getKey().longValue();
	}
	
	
	/**
	 * @param sql 要执行的DML和DDL类型SQL语句
	 * @throws DataAccessException
	 */
	protected void execute(String sql){
		getJdbcTemplate().execute(sql);
	}

	/**批量更新sql语句
	 * @param sql
	 * @return 受影响行数
	 * @throws DataAccessException
	 */
	protected int[] batchUpdate(String[] sql) {
		return getJdbcTemplate().batchUpdate(sql);
	}
	
	
	/**
	 * 查询int型数据
	 * @param sql
	 * @return
	 */
	protected Integer queryForInt(String sql){
		return getJdbcTemplate().queryForInt(sql);
	}
	
	/**
	 * 查询int型数据
	 * @param sql
	 * @return
	 */
	protected Integer queryForInt(String sql,Object... args){
		return getJdbcTemplate().queryForInt(sql, args);
	}
	
	/**
	 * 查询String型数据
	 * @param sql
	 * @return
	 */
	protected String queryForString(String sql){
		return getJdbcTemplate().queryForObject(sql, String.class);
	}
	
	/**
	 * 查询String型数据
	 * @param sql
	 * @return
	 */
	protected String queryForString(String sql,Object... args){
		return getJdbcTemplate().queryForObject(sql, String.class,args);
	}
	
	/**
	 * 查询long型数据
	 * @param sql
	 * @return
	 */
	protected Long queryForLong(String sql){
		return getJdbcTemplate().queryForLong(sql);
	}
	
	/**
	 * 查询long型数据
	 * @param sql
	 * @return
	 */
	protected Long queryForLong(String sql,Object... args){
		return getJdbcTemplate().queryForLong(sql, args);
		
	}
	
	/**
	 * 查询map型数据
	 * @param sql
	 * @return
	 */
	protected Map<String,Object> queryForMap(String sql){
		return getJdbcTemplate().queryForMap(sql);
	}
	
	
	/**
	 * 查询map型数据
	 * @param sql
	 * @return
	 */
	protected Map<String,Object> queryForMap(String sql,Object... args){
		return getJdbcTemplate().queryForMap(sql,args);
	}
	
	/**
	 * 查询List<Map<String,Object>>型数据
	 * @param sql
	 * @return
	 */
	 protected List<Map<String,Object>> queryForList(String sql){
		return getJdbcTemplate().queryForList(sql);
	}
	
	/**
	 * 查询List<Map<String,Object>>型数据
	 * @param sql
	 * @return
	 */
	 protected List<Map<String,Object>> queryForList(String sql,Object... args){
		return getJdbcTemplate().queryForList(sql,args);
	}
	
	
	 protected <T> T queryForObject(String sql,Class<T> requiredType){
		return getJdbcTemplate().queryForObject(sql,requiredType);
	}
	
	 protected <T> T queryForObject(String sql, Class<T> requiredType, Object... args){
		return getJdbcTemplate().queryForObject(sql,requiredType,args);
	}
	
	 protected <T> T queryForBean(Class<T> beanClass, String sql) {
		return getJdbcTemplate().queryForObject(sql,new BeanPropertyRowMapper<T>(beanClass));
	}
	
	 protected <T> T queryForBean(Class<T> beanClass, String sql,Object... args) {
		return getJdbcTemplate().queryForObject(sql,new BeanPropertyRowMapper<T>(beanClass),args);
	}
	
	 protected <T> List<T> queryForList(Class<T> beanClass, String sql) {
		return  getJdbcTemplate().query(sql, new BeanPropertyRowMapper<T>(beanClass));
	}
	
	 protected <T> List<T> queryForList(Class<T> beanClass, String sql, Object... args) {
		return  getJdbcTemplate().query(sql, new BeanPropertyRowMapper<T>(beanClass),args);
	}
	 
	 protected <T> List<T> query(String sql, RowMapper<T> rowMapper){
		 return getJdbcTemplate().query(sql, rowMapper);
	 }
	
	 
	 /**
	  * 由sql直接生成json串
	 * @param sql
	 * @param args
	 * @return
	 */
	public  JSONArray getJsonList(String sql,Object... args){
		 final JSONArray jsonArr=new JSONArray();
		 this.getJdbcTemplate().query(sql, args, new RowMapper<JSONArray>(){
			@Override
			public JSONArray mapRow(ResultSet rs, int rowNum)throws SQLException {
				ResultSetMetaData metaData=rs.getMetaData();
				int cols=metaData.getColumnCount();
				while(rs.next()){
					JSONObject jsonObj=new JSONObject();
					for(int i=1;i<=cols;i++){
						String colName=metaData.getColumnLabel(i);
						String value=rs.getString(colName);
						if(value!=null && value.length()!=0){
							jsonObj.put(colName.toLowerCase(), value);
						}
					}
					jsonArr.add(jsonObj);	
				}
				return jsonArr;
			}
		 });
		 return jsonArr;
	 }
	
	public  JSONObject getSingleJson(String sql,Object... args){
		JSONArray result=getJsonList(sql,args);
		if(result==null || result.size()==0){
			return null;
		}
		return result.getJSONObject(0);
	}
}
